/**
 * Copyright 2009 Takahiko Ito
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.unigram.oluolu.common;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

/**
 *
 */
public class Query implements
    WritableComparable <Query> {
    /** user Id Text. */
    private Text userId;

    /** query string submitted by user. */
    private Text queryStr;

    /** time query is submitted. */
    private LongWritable date;

    /**
     * Default Constructor.
     */
    public Query() {
        this.userId = new Text();
        this.queryStr = new Text();
        this.date = new LongWritable(0);
    }

    /**
     * Constructor.
     * @param inputQueryStr query string
     * @param inputDate date
     */
    public Query(final Text inputQueryStr,
            final LongWritable inputDate) {
        this.userId = new Text();
        this.queryStr = inputQueryStr;
        this.date = inputDate;
    }

    /**
     * Constructor.
     * @param inputUserId user id
     * @param inputQueryStr query string
     * @param inputDate time
     */
    public Query(final Text inputUserId, 
            final Text inputQueryStr, final LongWritable inputDate) {
        this.userId = inputUserId;
        this.queryStr = inputQueryStr;
        this.date = inputDate;
    }

    /**
     * Get userId who submit the query string.
     * @return userId user id
     */
    public final Text getUserId() {
        return userId;
    }

    /**
     * Get the time when user submitted query.
     * @return date the time when the query string is submitted.
     */
    public final LongWritable getDate() {
        return date;
    }

    /**
     * Return query string.
     * @return queryString - Text
     */
    public final Text getQueryString() {
        return queryStr;
    }

    /**
     * Write the query information for serialization.
     * @param out - DataOutput
     * @throws IOException -
     */
    public final void write(
            final DataOutput out)
        throws IOException {
        userId.write(out);
        queryStr.write(out);
        date.write(out);
    }

    /**
     * Read the serialized the query information.
     * @param in - DataInput
     * @throws IOException -
     */
    public final void readFields(final DataInput in)
        throws IOException {
        userId.readFields(in);
        queryStr.readFields(in);
        date.readFields(in);
    }
    
    /**
     * Compare query into another one.
     * 
     * @param other query to be compared
     * @return 1 when this is bigger than other
     *          0 when this is the same as other
     *         -1 when this is the smaller than other
     */
    public final int compareTo(final Query other) {
        // compare userId
        if (this.userId.compareTo(other.userId) > 0) {
            return 1;
        }
        if (this.userId.compareTo(other.userId) < 0) {
            return -1;
        }
        // compare date 
        if (this.date.compareTo(other.date) > 0) {
            return 1;
        }
        if (this.date.compareTo(other.date) < 0) {
            return -1;
        }
        // compare query string
        if (this.queryStr.compareTo(other.queryStr) > 0) {
            return 1;
        }
        if (this.queryStr.compareTo(other.queryStr) < 0) {
            return -1;
        }        
        return 0;
    }

    /**
     * Validate assigned Object(should Query instance) is the same
     * as this.
     * @param obj a object to be validated.
     * @return true when this and obj is identical contents
     *          false when this and obj is different
     */
    public final boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Query)) {
            return false;
        }

        if ((this.date.get() == ((Query) obj).date.get())
            && (this.queryStr.equals(((Query) obj).queryStr))
            && (this.userId.equals(((Query) obj).userId))) {
            return true;
        } 
        return false;
    }

    /**
     * hashCode.
     * @return hash value
     */
    public final int hashCode() {
        int result = 0;
        result += this.userId.hashCode();
        result += this.queryStr.hashCode();
        result += this.date.hashCode();
        return result;
    }
    
    /**
     * Return the Query log information which contains user id,query
     * string and time the query was submitted by the user.
     * 
     * The format is "UUUU\tQQQQ\tTTTT". Here UUUU, QQQQ and TTTT 
     * mean the user id, the query string and the long representation 
     * of the time respectively. 
     * @return String object containing the information of the Query 
     *          object. 
     */
    public final String toString() {
        return String.format("%s\t%s\t%d", 
                this.userId, this.queryStr, this.date);
    }

}
